/**
 * This file is part of 1genia trampoline
 * Copyright (C) 2007 1genia (contact@1genia.com)
 *
 * This library is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; version 3 of the License. 
 *
 * This library is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details. 
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; see the file COPYING.TXT.  If not,
 * write to the Free Software Foundation, Inc., 51 Franklin Street,
 * Fifth Floor, Boston, MA 02110-1301, USA. 
 **/
package com.genia.toolbox.persistence.hibernate.mapping.type;

import java.net.InetAddress;
import java.net.UnknownHostException;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;

import org.hibernate.HibernateException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * a hibernate type to stock inet adresses.
 */
public class InetAddressHibernateType
    extends AbstractImmutableUserType
{

  /**
   * the <code>Log</code> variabe.
   */
  private static final Logger LOGGER = LoggerFactory.getLogger(InetAddressHibernateType.class);

  /**
   * the SQL type of the column used to stock the reference to the object.
   */
  private static final int[] SQL_TYPES = { Types.VARBINARY };



  /**
   * Retrieve an instance of the mapped class from a JDBC resultset.
   * Implementors should handle possibility of null values.
   * 
   * @param rs
   *          a JDBC result set
   * @param names
   *          the column names
   * @param owner
   *          the containing entity
   * @return Object
   * @throws HibernateException
   *           if a hibernate error occurred
   * @throws SQLException
   *           if a SQL error occurred
   */
  public Object nullSafeGet(ResultSet rs, String[] names, Object owner)
      throws HibernateException, SQLException
  {
    byte[] bytes = rs.getBytes(names[0]);
    InetAddress result = null;
    if (!rs.wasNull()) {
      try {
        result = InetAddress.getByAddress(bytes);
      }
      catch (UnknownHostException e) {
        // Can't happen, no name conversion is made.
        LOGGER.error(e.getMessage(), e);
        throw new HibernateException(e);
      }
    }
    return result;
  }



  /**
   * Write an instance of the mapped class to a prepared statement. Implementors
   * should handle possibility of null values. A multi-column type should be
   * written to parameters starting from <tt>index</tt>.
   * 
   * @param st
   *          a JDBC prepared statement
   * @param value
   *          the object to write
   * @param index
   *          statement parameter index
   * @throws HibernateException
   *           if a hibernate error occurred
   * @throws SQLException
   *           if a SQL error occurred
   */
  public void nullSafeSet(PreparedStatement st, Object value, int index)
      throws HibernateException, SQLException
  {
    if (null == value) {
      st.setNull(index, Types.VARBINARY);
    }
    else {
      st.setBytes(index, ((InetAddress) value).getAddress());
    }
  }



  /**
   * The class returned by <tt>nullSafeGet()</tt>.
   * 
   * @return Class
   */
  public Class<?> returnedClass()
  {
    return InetAddress.class;
  }



  /**
   * Return the SQL type codes for the columns mapped by this type. The codes
   * are defined on <tt>java.sql.Types</tt>.
   * 
   * @see java.sql.Types
   * @return int[] the typecodes
   */
  public int[] sqlTypes()
  {
    return SQL_TYPES;
  }

}
